/**
 * Created by zhangguoyu on 16/4/27.
 */

var VisitedTotal = require('../models/VIsitedTotal');
var VisitedEveryday = require('../models/VisitedEveryday');
var co = require('co');
var moment = require('moment');
var response = require('../net/HttpResponse');
var AppLogsResolver = require('../resolvers/AppLogsResolver');
var ContentLogsResolver = require('../resolvers/ContentLogsResolver');
var MapReduceBuilder = require('../db/MapReduceBuilder');
var TempsApp = require('../models/temps/TempsApp');
var TempLogs = require('../models/logs/TempLogs');

var coreData = require('../resolvers/CoreData');

var ApiController = function () {
};

ApiController.prototype.onCreate = function () {
  var router = this.$router;
  router.use(function (req, res, next) {
    next();
  });
};

ApiController.prototype.getProduct = function (req, res) {
  var params = req.params;
  var biz = params.biz.toUpperCase();
  var productId = params.productid;
  co(function * () {
    var totalResult = yield VisitedTotal.findOne({ biz: biz }).limit(1).exec();
    var querySet = yield VisitedEveryday.find({ biz: biz }).sort({ date: -1 }).limit(30).exec();
    var data = {};
    data.totalVisited = '0';
    data.totalDurations = 0;
    data.avgDurations = 0;
    data.news = ['0', '0'];
    data.visited = ['0', '0'];
    data.durations = ['0', '0'];
    data.playCount = ['0', '0'];
    data.users = ['0', '0'];
    data.categories = [];

    var now = moment().format('YYYY-MM-DD');
    var yesterdayData = undefined;
    var todayData = undefined;
    if (querySet && querySet.length) {
      if (querySet[0].date === now) {
        todayData = querySet[0];
        if (querySet.length > 1) {
          yesterdayData = querySet[1];
        }
      } else {
        yesterdayData = querySet[0];
      }
    }

    var totalCategories = totalResult.categories;
    var ttci = totalCategories.length;
    while (ttci--) {
      var ttc = totalCategories[ttci];
      if (ttc.product === productId) {
        data.categories.push({
          id: ttc.id,
          name: ttc.name,
          news: ['0', '0'],
          visited: ['0', '0'],
          durations: ['0', '0'],
          playCount: ['0', '0'],
          users: 0
        })
      }
    }

    if (todayData) {
      var todayProducts = todayData.products;
      var tpi = todayProducts.length;
      while (tpi--) {
        var tp = todayProducts[tpi];
        if (tp.id === productId) {
          data.news[0] = '' + tp.data.news;
          data.visited[0] = '' + tp.data.visited;
          data.durations[0] = '' + tp.data.durations;
          data.playCount[0] = '' + tp.data.playCount;
          data.users[0] = '' + tp.data.users;
          break;
        }
      }
      var todayCategories = todayData.categories;
      var tci = todayCategories.length;
      while (tci--) {
        var tc = todayCategories[tci];
        if (tc.product !== productId) {
          continue;
        }
        var tdci = data.categories.length;
        while (tdci--) {
          var tdc = data.categories[tdci];
          if (tdc.id === tc.id) {
            tdc.news[0] = '' + tc.data.news;
            tdc.visited[0] = '' + tc.data.visited;
            tdc.durations[0] = '' + tc.data.durations;
            tdc.playCount[0] = '' + tc.data.playCount;
            break;
          }
        }
      }
    }

    if (yesterdayData) {
      var yesterdayProducts = yesterdayData.products;
      var ypi = yesterdayProducts.length;
      while (ypi--) {
        var yp = yesterdayProducts[ypi];
        if (yp.id === productId) {
          data.news[1] = '' + yp.data.news;
          data.visited[1] = '' + yp.data.visited;
          data.durations[1] = '' + yp.data.durations;
          data.playCount[1] = '' + yp.data.playCount;
          data.users[1] = '' + yp.data.users;
          break;
        }
      }
      var yesterdayCategories = yesterdayData.categories;
      var yci = yesterdayCategories.length;
      while (yci--) {
        var yc = yesterdayCategories[yci];
        if (yc.product !== productId) {
          continue;
        }
        var ydci = data.categories.length;
        while (ydci--) {
          var ydc = data.categories[ydci];
          if (ydc.id === yc.id) {
            ydc.news[1] = '' + yc.data.news;
            ydc.visited[1] = '' + yc.data.visited;
            ydc.durations[1] = '' + yc.data.durations;
            ydc.playCount[1] = '' + yc.data.playCount;
            break;
          }
        }
      }
    }

    var totalProducts = totalResult.products;
    var ttpi = totalProducts.length;
    while (ttpi--) {
      var ttp = totalProducts[ttpi];
      if (ttp.id === productId) {
        data.totalVisited = '' + ttp.data.visited;
        data.totalDurations = '' + ttp.data.durations;
        break;
      }
    }

    var eqi = querySet.length;
    var count = 0;
    while (eqi--) {
      var dayProducts = querySet[eqi].products;
      var eqpi = dayProducts.length;
      while (eqpi--) {
        if (dayProducts[eqpi].id === productId) {
          data.avgDurations += dayProducts[eqpi].data.durations;
          break;
        }
      }
      count++;
    }
    if (count > 0) {
      data.avgDurations = '' + parseInt(data.avgDurations / count);
    } else {
      data.avgDurations = '0';
    }

    res.json({
      code: 1,
      msg: 'ok',
      result: data
    });
  }.bind(this)).catch(function (err) {
    res.json({
      code: 0,
      msg: err.toString()
    })
  });
};

ApiController.prototype.getCategory = function (req, res) {
  var params = req.params;
  var biz = params.biz.toUpperCase();
  var productId = params.productid;
  var categoryId = params.categoryid;
  co(function * () {
    var totalResult = yield VisitedTotal.findOne({ biz: biz }).limit(1).exec();
    var querySet = yield VisitedEveryday.find({ biz: biz }).sort({ date: -1 }).limit(30).exec();
    var data = {};
    data.productId = productId;
    data.categoryId = categoryId;
    data.totalVisited = '0';
    data.totalDurations = '0';
    data.avgDurations = 0;
    data.news = ['0', '0'];
    data.visited = ['0', '0'];
    data.durations = ['0', '0'];
    data.playCount = ['0', '0'];
    data.users = ['0', '0'];
    data.contents = [];

    var now = moment().format('YYYY-MM-DD');
    var yesterdayData = undefined;
    var todayData = undefined;
    if (querySet && querySet.length) {
      if (querySet[0].date === now) {
        todayData = querySet[0];
        if (querySet.length > 1) {
          yesterdayData = querySet[1];
        }
      } else {
        yesterdayData = querySet[0];
      }
    }

    var totalContents = totalResult.contents;
    var ttcoi = totalContents.length;
    while (ttcoi--) {
      var ttco = totalContents[ttcoi];
      if (ttco.product === productId && ttco.category === categoryId) {
        data.contents.push({
          id: ttco.id,
          name: ttco.name,
          news: ['0', '0'],
          visited: ['0', '0'],
          durations: ['0', '0'],
          playCount: ['0', '0'],
          users: '0'
        })
      }
    }

    if (todayData) {
      var todayCategories = todayData.categories;
      var tci = todayCategories.length;
      while (tci--) {
        var tc = todayCategories[tci];
        if (tc.product === productId && tc.id === categoryId) {
          data.news[0] = '' + tc.data.news;
          data.visited[0] = '' + tc.data.visited;
          data.durations[0] = '' + tc.data.durations;
          data.playCount[0] = '' + tc.data.playCount;
          data.users[0] = '' + tc.data.users;
          break;
        }
      }
      var todayContents = todayData.contents;
      var tcoi = todayContents.length;
      while (tcoi--) {
        var tco = todayContents[tcoi];
        if (tco.product !== productId || tco.category !== categoryId) {
          continue;
        }
        var tdcoi = data.contents.length;
        while (tdcoi--) {
          var tdco = data.contents[tdcoi];
          if (tdco.id === tco.id) {
            tdco.news[0] = '' + tco.data.news;
            tdco.visited[0] = '' + tco.data.visited;
            tdco.durations[0] = '' + tco.data.durations;
            tdco.playCount[0] = '' + tco.data.playCount;
            tdco.users = '' + tco.data.user;
            break;
          }
        }
      }
    }

    if (yesterdayData) {
      var yesterdayCategories = yesterdayData.categories;
      var yci = yesterdayCategories.length;
      while (yci--) {
        var yc = yesterdayCategories[yci];
        if (yc.product === productId && yc.id === categoryId) {
          data.news[1] = '' + yc.data.news;
          data.visited[1] = '' + yc.data.visited;
          data.durations[1] = '' + yc.data.durations;
          data.playCount[1] = '' + yc.data.playCount;
          data.users[1] = '' + yc.data.users;
          break;
        }
      }
      var yesterdayContents = yesterdayData.contents;
      var ycoi = yesterdayContents.length;
      while (ycoi--) {
        var yco = yesterdayContents[ycoi];
        if (yco.product !== productId || yco.category !== categoryId) {
          continue;
        }
        var ydcoi = data.contents.length;
        while (ydcoi--) {
          var ydco = data.contents[ydcoi];
          if (ydco.id === yco.id) {
            ydco.news[1] = '' + yco.data.news;
            ydco.visited[1] = '' + yco.data.visited;
            ydco.durations[1] = '' + yco.data.durations;
            ydco.playCount[1] = '' + yco.data.playCount;
            ydco.users = '' + yco.data.users;
            break;
          }
        }
      }
    }

    var totalCategories = totalResult.categories;
    var ttcai = totalCategories.length;
    while (ttcai--) {
      var ttca = totalCategories[ttcai];
      if (ttca.product === productId && ttca.id === categoryId) {
        data.totalVisited = '' + ttca.data.visited;
        data.totalDurations = '' + ttca.data.durations;
        break;
      }
    }

    var eqi = querySet.length;
    var count = 0;
    while (eqi--) {
      var dayCategories = querySet[eqi].categories;
      var eqci = dayCategories.length;
      while (eqci--) {
        var dc = dayCategories[eqci];
        if (dc.product === productId && dc.id === categoryId) {
          data.avgDurations += dc.data.durations;
          break;
        }
      }
      count++;
    }
    if (count > 0) {
      data.avgDurations = '' + parseInt(data.avgDurations / count);
    } else {
      data.avgDurations = '0';
    }

    res.json({
      code: 1,
      msg: 'ok',
      result: data
    });
  }.bind(this)).catch(function (err) {
    res.json({
      code: 0,
      msg: err.toString()
    })
  });
};

ApiController.prototype.getContent = function (req, res) {

};

ApiController.prototype.getGlobal = function (req, res) {
  var params = req.params;
  var biz = params.biz.toUpperCase();
  co(function * () {
    var result = yield VisitedTotal.findOne({ biz: biz }).limit(1).exec();
    var querySet = yield VisitedEveryday.find({ biz: biz }).sort({ date: -1 }).limit(30).exec();
    var data = {};
    var now = moment().format('YYYY-MM-DD');
    var yesterdayData = undefined;
    var todayData = undefined;
    if (querySet && querySet.length) {
      if (querySet[0].date === now) {
        todayData = querySet[0];
        if (querySet.length > 1) {
          yesterdayData = querySet[1];
        }
      } else {
        yesterdayData = querySet[0];
      }
    }
    data.news = ['0', '0'];
    data.visited = ['0', '0'];
    data.orders = ['0', '0'];
    data.users = ['0', '0'];
    data.totalUsers = '' + result.data.users;
    data.totalVisited = '' + result.data.visited;
    data.totalOrders = '0';

    if (todayData) {
      data.news[0] = '' + todayData.data.news;
      data.visited[0] = '' + todayData.data.visited;
      data.users[0] = '' + todayData.data.users;
    }

    if (yesterdayData) {
      data.news[1] = '' + yesterdayData.data.news;
      data.visited[1] = '' + yesterdayData.data.visited;
      data.users[1] = '' + yesterdayData.data.users;
    }

    data.latest = [];
    querySet.forEach(function (item) {
      data.latest.push({
        date: item.date,
        visited: item.data.visited
      });
    });
    data.flavors = [];
    result.flavors.forEach(function (flavor) {
      data.flavors.push({
        name: flavor.name,
        visited: '' + flavor.data.visited
      });
    });
    data.products = [];
    result.products.forEach(function (product) {
      var prodData = {
        id: product.id,
        name: product.name,
        users: '' + product.data.users,
        news: ['0', '0'],
        visited: ['0', '0'],
        orders: ['0', '0']
      };
      if (todayData) {
        var p1List = todayData.products;
        var p1i = p1List.length;
        while (p1i--) {
          var p1Item = p1List[p1i];
          if (p1Item.id === product.id) {
            prodData.news[0] = '' + p1Item.data.news;
            prodData.visited[0] = '' + p1Item.data.visited;
            break;
          }
        }
      }
      if (yesterdayData) {
        var p2List = yesterdayData.products;
        var p2i = p2List.length;
        while (p2i--) {
          var p2Item = p2List[p2i];
          if (p2Item.id === product.id) {
            prodData.news[1] = '' + p2Item.data.news;
            prodData.visited[1] = '' + p2Item.data.visited;
            break;
          }
        }
      }
      data.products.push(prodData);
    });

    res.json({
      code: 1,
      msg: 'ok',
      result: data
    });
  }.bind(this)).catch(function (err) {
    res.json({
      code: 0,
      msg: err.toString()
    })
  });
};

ApiController.prototype.resolveAppLogs = function (req, res) {
  co(function * () {
    var resolver = new AppLogsResolver();
    var querySet = yield resolver.resolve();
    var core = coreData;
    response(res)
      .ok()
      .send(querySet);
  }).catch(function (err) {
    response(res)
      .error(err.toString())
      .send();
  });
};

ApiController.prototype.resolveContentLogs = function (req, res) {
  co(function * () {
    var core = coreData;
    var resolver = new ContentLogsResolver();
    var querySet = yield resolver.resolve();
    response(res)
      .ok()
      .send(querySet);
  }).catch(function (err) {
    response(res)
      .error(err.toString())
      .send();
  });
};

ApiController.prototype.resolveAppTotal = function (req, res) {
  co(function * () {
    var mapReduceResult = yield TempsApp.$manager.mapReduce(new MapReduceBuilder()
      .map(function () {
        var id = this._id.split('|');
        var value = this.value;
        emit(id[0], { visited: value.visited });
      })
      .reduce(function (key, values) {
        var reduceRes = {
          visited: 0
        };
        values.forEach(function (item) {
          reduceRes.visited += item.visited
        });
        return reduceRes;
      })
      .out({ replace: 'tempsout'})
      .create());
    var resultModel = mapReduceResult.model;
    var querySet = yield resultModel.$manager.all();
    var everydayQuerySet = querySet.map(function (item) {
      return {
        date: item._id,
        visited: item.value.visited
      }
    });

    mapReduceResult = yield TempsApp.$manager.mapReduce(new MapReduceBuilder()
      .map(function () {
        var id = this._id.split('|');
        var value = this.value;
        emit(id[3], { visited: value.visited });
      })
      .reduce(function (key, values) {
        var reduceRes = {
          visited: 0
        };
        values.forEach(function (item) {
          reduceRes.visited += item.visited;
        });
        return reduceRes;
      })
      .out({ replace: 'tempsout' })
      .create());

    resultModel = mapReduceResult.model;
    querySet = yield resultModel.$manager.all();
    var flavorsQuerySet = querySet.map(function (item) {
      return {
        flavor: item._id,
        visited: item.value.visited
      }
    });
    response(res)
      .ok()
      .send({
        everyday: everydayQuerySet,
        flavors: flavorsQuerySet
      })
  }).catch(function (err) {
    response(res)
      .error(err.toString())
      .send();
  })
};

ApiController.prototype.mergeToApp = function (req, res) {
  co(function * () {
    var result = yield TempLogs.$manager.mergeToAppLogs();
    response(res).ok().send(result);
  }).catch(function (err) {
    response(res).error(err.toString()).send();
  });
};

ApiController.prototype.onRouting = function (router) {
  router.get('/:biz', this.getGlobal);
  router.get('/:biz/product/:productid', this.getProduct);
  router.get('/:biz/product/:productid/category/:categoryid', this.getCategory);
  router.get('/:biz/product/:productid/category/:categoryid/content/:contentid', this.getContent);
  router.get('/resolve/app', this.resolveAppLogs);
  router.get('/resolve/content', this.resolveContentLogs);
  router.get('/app/total', this.resolveAppTotal);
  router.get('/temp/merge', this.mergeToApp);
};

module.exports = ApiController;